import asyncHandler from "express-async-handler";
import { body, validationResult } from "express-validator";

import Book from "../models/book";
import Genre from "../models/genre";

// 显示所有的流派。
export const genre_list = asyncHandler(async (req, res, next) => {
  const allGenres = await Genre.find().sort({ name: 1 }).exec();
  res.render("genre_list", { title: "Genre List", genre_list: allGenres });
});

// 显示特定流派的详情页。
export const genre_detail = asyncHandler(async (req, res, next) => {
  const findGenreById = () => Genre.findById(req.params.id).exec();
  const findGenreBooksById = () => Book.find({ genre: req.params.id }).exec();
  Promise.all([findGenreById(), findGenreBooksById()])
    .then((results) => {
      res.render("genre_detail", {
        title: "Genre Detail",
        genre: results[0],
        genre_books: results[1],
      });
    })
    .catch((err) => {
      next(err);
    });
});

// 通过 GET 显示创建流派。
export const genre_create_get = (req, res, next) => {
  res.render("genre_form", { title: "Create Genre" });
};

// 以 POST 方式处理创建流派。
export const genre_create_post = [
  // 校验类别名称长度
  body("name", "Genre name must contain at least 3 characters")
    .trim()
    .isLength({ min: 3 })
    .escape(),
  // 处理验证及清理过后的请求
  asyncHandler(async (req, res, next) => {
    // 从请求中提取验证时产生的错误信息
    const errors = validationResult(req);

    // 使用经过去除空白字符和转义处理的数据创建一个类型对象
    const genre = new Genre({ name: req.body.name });
    if (!errors.isEmpty()) {
      // 如果有错误，重新渲染表单
      res.render("genre_form", {
        title: "Create Genre",
        genre: genre,
        errors: errors.array(),
      });
      return;
    } else {
      // 有效数据
      // 检查同名 Genre 是否已存在
      const genreExists = await Genre.findOne({ name: req.body.name })
        .collation({ locale: "en", strength: 2 })
        .exec();
      if (genreExists) {
        // 存在同名 Genre，重定向到详情页
        res.redirect(genreExists.url);
      } else {
        await genre.save();
        // 保存新创建的 Genre，然后重定向到详情页
        res.redirect(genre.url);
      }
    }
  }),
];
// export const genre_create_post = asyncHandler(async (req, res, next) => {
//   res.send("未实现：流派创建 POST");
// });

// 通过 GET 显示流派删除表单。
export const genre_delete_get = asyncHandler(async (req, res, next) => {
  const [genre, allBooks] = await Promise.all([
    Genre.findById(req.params.id).exec(),
    Book.find({ genre: req.params.id }).exec(),
  ]);
  if (genre === null) {
    const error = new Error("Genre not found");
    error.status = 404;
    next(error);
  } else {
    res.render("genre_delete", {
      title: "Delete Genre",
      genre,
      genre_books: allBooks,
    });
  }
});

// 处理 POST 时的流派删除。
export const genre_delete_post = asyncHandler(async (req, res, next) => {
  const [genre, booksInGenre] = await Promise.all([
    Genre.findById(req.params.id).exec(),
    Book.find({ genre: req.params.id }, "title summary").exec(),
  ]);

  if (booksInGenre.length > 0) {
    res.render("genre_delete", {
      title: "Delete Genre",
      genre,
      genre_books: booksInGenre,
    });
  } else {
    await Genre.findByIdAndDelete(req.body.id);
    res.redirect("/catalog/genres");
  }
  res.send("未实现：流派删除 POST");
});

// 通过 GET 显示流派更新表单。
export const genre_update_get = asyncHandler(async (req, res, next) => {
  const genre = await Genre.findById(req.params.id).exec();
  if (genre === null) {
    const err = new Error("Genre not found");
    err.status = 404;
    return next(err);
  } else {
    res.render("genre_form", {
      title: "Update Genre",
      genre,
    });
  }
  res.send("未实现：流派更新 GET");
});

// 处理 POST 上的流派更新。
export const genre_update_post = [
  body("name", "Genre name must contain at least 3 characters")
    .trim()
    .isLength({ min: 3 })
    .escape(),
  asyncHandler(async (req, res, next) => {
    const errors = validationResult(req);

    const genre = new Genre({
      name: req.body.name,
      _id: req.params.id,
    });

    if (!errors.isEmpty()) {
      res.render("genre_form", {
        title: "Update Genre",
        genre,
        errors: errors.array(),
      });
    } else {
      await Genre.findByIdAndUpdate(req.params.id, genre, {});
      res.redirect("/catalog/genres");
    }
  }),
];
